﻿using SharpDepend.Datatypes;
using SharpDepend.WinRT.Classes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace SharpDepend.WinRT
{
    class MulticastManager : ISocketMulticastManager
    {
        private class Multicast : ISocketMulticast
        {
            private DatagramSocket mSocket;
            private List<byte[]> mReceavedData;

            /// <summary>
            /// Reference: http://stackoverflow.com/questions/14014675/unauthorizedaccessexception-when-trying-to-listen-to-multicast-group-in-c-sharp
            /// </summary>
            public Multicast()
            {
                mSocket = new DatagramSocket();
                mSocket.MessageReceived += socket_MessageReceived;

                mReceavedData = new List<byte[]>();
            }

            private void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
            {
                DataReader reader = args.GetDataReader();

                byte[] data = new byte[reader.UnconsumedBufferLength];
                reader.ReadBytes(data);

                mReceavedData.Add(data);
            }

            public BoolResult CreateMulticastSender(string ip, int port)
            {
                return new BoolResult(new NotImplementedException());
            }

            public BoolResult CreateMulticastListener(string ip, int port)
            {
                try
                {
                    HostName hostname = new HostName(ip);
                    var handle = mSocket.BindEndpointAsync(hostname, port.ToString());

                    Helper.WaitToComplete(handle);

                    if (handle.ErrorCode != null)
                    {
                        return new BoolResult(handle.ErrorCode);
                    }

                    mSocket.JoinMulticastGroup(hostname);
                }
                catch(Exception error)
                {
                    return new BoolResult(error);
                }

                return BoolResult.Succeded;
            }

            public void Write(byte[] data, int length)
            {
                throw new NotImplementedException();
            }

            public void Read(MulticastListenerResult result)
            {
                while (mReceavedData.Count == 0)
                {
                    SharpDepend.Manager.ThreadManager.Sleep(100);
                }

                byte[] data = mReceavedData[0];
                mReceavedData.RemoveAt(0);
                result(data);
            }

            public void Dispose()
            {
                mSocket.Dispose();
            }
        }
        public ISocketMulticast CreateMulticast()
        {
            return new Multicast();
        }
    }
}
